#include "vtor_heap.h"

#ifdef __VTOR_HEAP__


// 内存管理算法，用于malloc和free
// 参考 https://zhuanlan.zhihu.com/p/1084364537


void VtorHeap_PrintInfo(int heapIdx)
{
	int i = 0;
	VtorHeapNode* headHeapNode = VtorHeap_GetHeadNode(heapIdx);
	if (NULL == headHeapNode)
	{
		return ;
	}
	VtorHeapDebug("VtorHeap %d addr 0x%x len %d(0x%x)\r\n",
		heapIdx,
		headHeapNode,
		headHeapNode->heapLen,
		headHeapNode->heapLen);

	VtorHeapNode* curHeapNode = headHeapNode->nextHeapNode;

	while (NULL != curHeapNode)
	{
		VtorHeapDebug("VtorHeap %d addr 0x%x len %d(0x%x) magicNumber 0x%x\r\n",
			i,
			curHeapNode + 1,
			curHeapNode->heapLen,
			curHeapNode->heapLen,
			curHeapNode->heapHeadMagicNumber);

		i++;
		curHeapNode = curHeapNode->nextHeapNode;
	}
	VtorHeapDebug("\r\n");
}

void* VtorHeapx_Malloc(int heapIdx, int userSize)
{
	VtorHeapNode* headHeapNode = VtorHeap_GetHeadNode(heapIdx);
	if (NULL == headHeapNode || 0 == userSize)
	{
		return NULL;
	}
	VtorHeapNode* curHeapNode = headHeapNode->nextHeapNode;
	VtorHeapNode* userHeapNode = NULL;
#if VTOR_HEAP_ALIGNED
	userSize += VTOR_HEAP_ALIGNED - 1;
	userSize &= ~(VTOR_HEAP_ALIGNED - 1);
#endif
	int actSize = userSize + sizeof(VtorHeapNode);
	
	while (NULL != curHeapNode)
	{
		// 如果空间足够（必须满足能放下申请的内存，和内存头）
		// 且未被分配
		if (curHeapNode->heapLen >= actSize
			&& VtorHeapFreeNumber == curHeapNode->heapHeadMagicNumber)
		{
			// user先指向这里，等待cur赋值完毕，再更新参数
			userHeapNode = curHeapNode;

			// 跳过实际使用的内存，调整链表，设置此段heap属于os
			curHeapNode = (VtorHeapNode*)((char*)curHeapNode + actSize);
			curHeapNode->nextHeapNode = userHeapNode->nextHeapNode;
			curHeapNode->heapLen = userHeapNode->heapLen - actSize;
			curHeapNode->heapHeadMagicNumber = VtorHeapFreeNumber;


			userHeapNode->nextHeapNode = curHeapNode;
			userHeapNode->heapLen = userSize;
			// 设置魔鬼数字，表明从  vtorheap  给  user
			userHeapNode->heapHeadMagicNumber = VtorHeapMallocNumber;
			// 返回节点指向的内存（需跳过偏移）
			break;
		}
		// 指向下一个node
		curHeapNode = curHeapNode->nextHeapNode;
	}
	if (userHeapNode)
	{
		unsigned char* userBuf = (unsigned char*)(userHeapNode + 1);
		//VtorHeapDebug("VtorHeap_Malloc 0x%x %d(0x%x)\r\n",
		//	userBuf, userSize, userSize);
		return userBuf;
	}
	else
	{
		VtorHeapDebug("VtorHeap_Malloc fail %d(0x%x)\r\n",
			 userSize, userSize);
	}
	return NULL;
}

void VtorHeapx_Free(int heapIdx, void* heapBuf)
{
	// 判断是否在某段区域内

	VtorHeapNode* headHeapNode = VtorHeap_GetHeadNode(heapIdx);
	if (NULL == headHeapNode || NULL == heapBuf)
	{
		return ;
	}
	if ((char*)heapBuf < (char*)headHeapNode
		|| (char*)heapBuf >= (char*)headHeapNode + headHeapNode->heapLen)
	{
		return ; // 超出范围，不属于该管理的内存
	}

	VtorHeapNode* preHeapNode = headHeapNode;
	VtorHeapNode* curHeapNode = headHeapNode->nextHeapNode;
	VtorHeapNode* userHeapNode = (VtorHeapNode*)(heapBuf) - 1;

	// 如果魔鬼数字失效，说明此内存有问题，应该处理错误 ，可以直接返回
	if (VtorHeapMallocNumber != userHeapNode->heapHeadMagicNumber)
	{
		// 错误处理，可能是重free，可能是乱传的地址
		VtorHeapDebug("VtorHeap_Free Error 0x%x\r\n", heapBuf);
		return;
	}

	//VtorHeapDebug("VtorHeap_Free 0x%x %d(0x%x)\r\n",
	//	heapBuf, userHeapNode->heapLen, userHeapNode->heapLen);

	while (NULL != curHeapNode)
	{

		if (userHeapNode == curHeapNode)
		{
			// 将内存 从 user 返回给 vtorheap ，同步设置魔鬼数字
			userHeapNode->heapHeadMagicNumber = VtorHeapFreeNumber;
			break;
		}
		preHeapNode = preHeapNode->nextHeapNode;
		curHeapNode = curHeapNode->nextHeapNode;
	}
	if (NULL != curHeapNode)
	{
		VtorHeapNode* nextHeapNode = curHeapNode->nextHeapNode;
		// 将cur长度合并到user中
		if (nextHeapNode
			&& nextHeapNode->heapHeadMagicNumber == VtorHeapFreeNumber)
		{
			curHeapNode->heapLen += sizeof(VtorHeapNode);
			curHeapNode->heapLen += nextHeapNode->heapLen;
			curHeapNode->nextHeapNode = nextHeapNode->nextHeapNode;
		}
		if (preHeapNode != headHeapNode
			&& preHeapNode->heapHeadMagicNumber == VtorHeapFreeNumber)
		{
			// 将user长度合并到pre中
			preHeapNode->heapLen += sizeof(VtorHeapNode);
			preHeapNode->heapLen += curHeapNode->heapLen;
			preHeapNode->nextHeapNode = curHeapNode->nextHeapNode;
		}
	}
}


void* VtorHeapx_Realloc(int heapIdx, void* heapBuf, int newsize)
{
	VtorHeapNode* headHeapNode = VtorHeap_GetHeadNode(heapIdx);
	VtorHeapNode* oldUserHeapNode = (VtorHeapNode*)(heapBuf)-1;
	if (NULL == headHeapNode)
	{
		return NULL;
	}
	if (NULL == heapBuf)
	{
		return VtorHeapx_Malloc(heapIdx, newsize);
	}
	if (newsize <= oldUserHeapNode->heapLen)
	{
		return heapBuf;
	}
	
	uint8_t* newbuffer = NULL;
	
	newbuffer = (uint8_t*)VtorHeapx_Malloc(heapIdx, newsize);
	if (NULL == newbuffer)
	{
		VtorHeapx_Free(heapIdx, heapBuf);
		return NULL;
	}
	memcpy(newbuffer, heapBuf, oldUserHeapNode->heapLen);
	VtorHeapx_Free(heapIdx, heapBuf);
	return newbuffer;
}


VtorHeapNode* VtorHeapx_Init(int heapIdx, void* heapBuf, int heapSize)
{
	// 内存管理头节点
	VtorHeap_SetHeadNode(heapIdx, heapBuf);
	VtorHeapNode* headHeapNode = (VtorHeapNode*)heapBuf;
	if (NULL == headHeapNode)
	{
		return NULL;
	}
	// 需要存放next指针，长度，魔鬼数字等信息
	// 所以实际heapLen略小于分配出的内存
	headHeapNode->heapLen = heapSize - sizeof(VtorHeapNode);
	headHeapNode->heapHeadMagicNumber = VtorHeapFreeNumber;
	// 直接创建头节点，便于后续操作
	VtorHeapNode* curHeapNode = headHeapNode + 1;
	// 挤出空间存放头指针和尾指针.
	curHeapNode->heapLen = headHeapNode->heapLen - sizeof(VtorHeapNode);
	curHeapNode->heapHeadMagicNumber = VtorHeapFreeNumber;

	headHeapNode->nextHeapNode = curHeapNode;
	curHeapNode->nextHeapNode = NULL;

	return headHeapNode;
}


#endif // __VTOR_HEAP__

